﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VersionChange
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args == null || args.Length <= 0)
            {
                WaitCommond();
            }
            else
            {
                Analysis(args);
            }
        }

        static void WaitCommond()
        {
            Console.WriteLine("输入 h 并回车查看帮助");
            Console.WriteLine("f [文本文件路径] p [文本文件第几行],[版本号字符串起始位]... a/s/r [增减的版本数]");
            while (true)
            {
                var command = Console.ReadLine();
                if (string.IsNullOrEmpty(command)) continue;
                if ("exit".Equals(command.ToLower())) return;
                if ("h".Equals(command.ToLower()))
                {
                    Console.WriteLine("输入 exit 并回车退出程序");
                    Console.WriteLine("");
                    Console.WriteLine("a 版本号增加 [版本号增加数，默认1]");
                    Console.WriteLine("s 版本号递减 [版本号递减数，默认1]");
                    Console.WriteLine("r 读取版本号");
                    Console.WriteLine("p 版本号位置 [第几行],[第几个字符串]... (可多个参数)");
                    Console.WriteLine("f [文本文件路径]");
                }
                else
                {
                    var commands = command.Split(' ');
                    Analysis(commands);
                }
            }
        }

        /// <summary>
        /// 解析命令
        /// </summary>
        /// <param name="args"></param>
        static void Analysis(string[] args)
        {
            if (args == null || args.Length <= 0)
            {
                Console.WriteLine("请输入命令");
                return;
            }
            string filePath = null;
            string command = null;
            int commandParam = 1;
            List<Position> positions = new List<Position>();
            for (int i = 0; i < args.Length; i++)
            {
                var common = args[i].ToLower();
                if ("f".Equals(common) && args.Length > i + 1)
                {
                    var temp = args[i + 1];
                    if (System.IO.File.Exists(temp)) filePath = temp;
                }
                else if ("a".Equals(common) || "s".Equals(common) || "r".Equals(common))
                {
                    command = common;
                    if (args.Length > i + 1)
                    {
                        var temp = args[i + 1].ToLower();
                        if (!"f".Equals(temp) && !"p".Equals(temp) && int.TryParse(temp, out int count)) commandParam = count;
                    }
                }
                else if ("p".Equals(common))
                {
                    if (args.Length > i + 1)
                    {
                        for (int j = i + 1; j < args.Length; j++)
                        {
                            var temp = args[j];
                            if ("f".Equals(temp) || "a".Equals(temp) || "s".Equals(temp) || "r".Equals(temp)) break;
                            var temps = temp.Split(',');
                            if (temps.Length != 2 || !int.TryParse(temps[0], out int l) || !int.TryParse(temps[1], out int b))
                            {
                                Console.WriteLine(string.Format("{0}不是有效参数，请正确输入参数p", temp));
                                return;
                            }
                            positions.Add(new Position() { Line = l, Begin = b });
                        }
                    }
                    else
                    {
                        Console.WriteLine("请正确输入参数 Line");
                        return;
                    }
                }

            }
            if (string.IsNullOrEmpty(filePath))
            {
                Console.WriteLine("请正确输入文本文件路径并确保文件存在");
                return;
            }
            if (string.IsNullOrEmpty(command))
            {
                Console.WriteLine("请正确输入操作命令；a：版本号+1；s：版本号-1；r：读取");
                return;
            }
            if (positions.Count <= 0)
            {
                Console.WriteLine("请输入参数p");
                return;
            }
            try
            {
                Execute(filePath, command, commandParam, positions.ToArray());
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="command"></param>
        /// <param name="count"></param>
        /// <param name="positions"></param>
        static void Execute(string filePath, string command, int count, params Position[] positions)
        {
            var lines = System.IO.File.ReadAllLines(filePath, Encoding.UTF8);
            var maxline = positions.Max(p => p.Line);
            if (lines.Length <= maxline)
            {
                Console.WriteLine(string.Format("文件行数({0})小于需要修改的行数（{1}）", lines.Length, maxline));
                return;
            }
            switch (command)
            {
                case "a":
                case "s":
                    foreach (var position in positions)
                    {
                        var strline = lines[position.Line];
                        if (strline.Length < position.Begin)
                        {
                            Console.WriteLine(string.Format("第{0}行字符串字节数（{1}）小于需要截取的位置（起始位：{2}）", position.Line, strline.Length, position.Begin));
                            return;
                        }
                        int end = position.Begin;
                        for (int i = position.Begin; i < strline.Length; i++)
                        {
                            var c = strline[i];
                            if (!VersionChar.Contains(c)) break;
                            else end = i + 1;
                        }
                        string strversion = strline.Substring(position.Begin, end - position.Begin).Trim(',');
                        if (Version.TryParse(strversion, out Version v))
                        {
                            Version newv = "a".Equals(command) ? VersionAdd(v, count) : VersionSubtract(v, count);
                            string newline = string.Concat(strline.Substring(0, position.Begin), newv.ToString(), strline.Substring(end));
                            lines[position.Line] = newline;
                            Console.WriteLine(string.Format("{0} => {1}", strversion, newv.ToString()));
                        }
                        else
                        {
                            Console.WriteLine(string.Format("{0}不是有效的版本号字符串", strversion));
                            return;
                        }
                    }
                    System.IO.File.WriteAllLines(filePath, lines, Encoding.UTF8);
                    Console.WriteLine(string.Format("版本号修改成功 {0}", filePath));
                    break;
                default:
                    foreach (var position in positions)
                    {
                        Console.WriteLine(string.Format("{0}：{1}", position.Line, lines[position.Line].Substring(position.Begin)));
                    }
                    break;
            }
        }

        /// <summary>
        /// 版本号加
        /// </summary>
        /// <param name="v">版本号</param>
        /// <param name="i">加的数值</param>
        /// <returns></returns>
        static Version VersionAdd(Version v, int i = 1)
        {
            int m1 = v.Major;
            int m2 = v.Minor;
            int m3 = v.Build;
            int m4 = v.Revision + i;
            if (m4 >= 100)
            {
                m3 += m4 / 100;
                m4 = m4 % 100;
            }
            if (m3 >= 100)
            {
                m2 += m3 / 100;
                m3 = m3 % 100;
            }
            if (m2 >= 100)
            {
                m1 += m2 / 100;
                m2 = m2 % 100;
            }
            return new Version(m1, m2, m3, m4);
        }

        /// <summary>
        /// 版本号减
        /// </summary>
        /// <param name="v">版本号</param>
        /// <param name="i">减的数值</param>
        /// <returns></returns>
        static Version VersionSubtract(Version v, int i = 1)
        {
            int m1 = v.Major;
            int m2 = v.Minor;
            int m3 = v.Build;
            int m4 = v.Revision - i;
            if (m4 < 0)
            {
                m3 -= m4 / 100;
                m4 = m4 + 100;
            }
            if (m3 < 0)
            {
                m2 -= m3 / 100;
                m3 = m3 + 100;
            }
            if (m2 < 0)
            {
                m1 -= m2 / 100;
                m2 = m2 + 100;
            }
            return new Version(m1, m2, m3, m4);
        }

        static char[] VersionChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' };
    }

    struct Position
    {
        public int Line { get; set; }
        public int Begin { get; set; }
    }
}
